#ifndef PROJECT_HPP_INCLUDED
#define PROJECT_HPP_INCLUDED

#include <map>
#include <string>
#include <vector>

#include "building_fwd.hpp"
#include "city_fwd.hpp"
#include "project_fwd.hpp"
#include "tile_logic.hpp"
#include "tile_fwd.hpp"

class world;

class project
{
public:
	virtual ~project();
	int labor_complete() const;
	int labor_required() const;
	void apply_labor(int amount);
	bool complete() const;
	void apply_results(world& w) { do_apply(w); }
	const std::vector<hex::location>& locs() const { return locs_; }
	virtual void draw() const;
	virtual void draw_loc(const hex::location& loc) const = 0;

	virtual std::string description() const = 0;
protected:
	explicit project(city* c);
	void set_labor_requirement(int amount);
	void set_locs(const std::vector<hex::location>& locs);
private:
	virtual void do_apply(world& w) = 0;
	city* city_;
	int labor_complete_;
	int labor_required_;
	std::vector<hex::location> locs_;
};

class road_project : public project
{
public:
	road_project(const world& w, city* c, const std::vector<hex::location>& locs);
	void draw_loc(const hex::location& loc) const;
	std::string description() const;

private:
	void do_apply(world& w);
	int calculate_difficulty() const;
};

class building_project : public project
{
public:
	building_project(city_ptr c, const_building_type_ptr b);
	std::string description() const;
	void draw_loc(const hex::location& loc) const;

private:
	void do_apply(world& w);

	city_ptr city_;
	const_building_type_ptr building_;
};

class improvement_project : public project
{
public:
	explicit improvement_project(city_ptr c, hex::tile_ptr t);
	void draw_loc(const hex::location& loc) const;
	std::string description() const;
private:
	void do_apply(world& w);

	const_city_ptr city_;
	hex::tile_ptr tile_;
};

#endif
